Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Node / ReticulumProjects / MeshChatX.git / files / tests / backend / test_concurrency_stress.py

Displaying Raw • Download


tests/backend/test_concurrency_stress.py b84ade45f85f685ba96b829bf0e9afcb5b014079 (b84ade45) Text, 5.72 KB

T8b949e# SPDX-License-Identifier: 0BSD

Tff7b72import T7ee787os
Tff7b72import T7ee787secrets
Tff7b72import T7ee787shutil
Tff7b72import T7ee787tempfile
Tff7b72import T7ee787threading
Tff7b72import T7ee787time
Tff7b72import T7ee787unittest

Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787database Tff7b72import Te6edf3Database
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787databaseT7ee787.T7ee787provider Tff7b72import Te6edf3DatabaseProvider
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787identity_manager Tff7b72import Te6edf3IdentityManager


Tff7b72class T56d364TestConcurrencyStressTb4b4b4(Te6edf3unittestTff7b72.Td2a8ffTestCaseTb4b4b4)Tb4b4b4:
Tff7b72def Td2a8ffsetUpTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# Reset DatabaseProvider singleton for clean state
Te6edf3DatabaseProviderTff7b72.Td2a8ff_instance Tff7b72= Tff7b72None

Tff7b72selfTff7b72.Td2a8fftest_dir Tff7b72= Te6edf3tempfileTff7b72.Td2a8ffmkdtempTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffdb_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8fftest_dirTb4b4b4, Ta5d6ff"Ta5d6ffstress.dbTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffdb Tff7b72= Te6edf3DatabaseTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdb_pathTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffdbTff7b72.Td2a8ffinitializeTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffstop_threads Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8fferrors Tff7b72= Tb4b4b4[Tb4b4b4]

Tff7b72def Td2a8fftearDownTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffstop_threads Tff7b72= Tff7b72True
Tff7b72selfTff7b72.Td2a8ffdbTff7b72.Td2a8ffclose_allTb4b4b4(Tb4b4b4)
T8b949e# Reset again
Te6edf3DatabaseProviderTff7b72.Td2a8ff_instance Tff7b72= Tff7b72None
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Tff7b72selfTff7b72.Td2a8fftest_dirTb4b4b4)Tb4b4b4:
Te6edf3shutilTff7b72.Td2a8ffrmtreeTb4b4b4(Tff7b72selfTff7b72.Td2a8fftest_dirTb4b4b4)

Tff7b72def Td2a8ffdb_writer_workerTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3worker_idTb4b4b4)Tb4b4b4:
T8b949e"""Spams the message table with inserts and updates."""
Tff7b72tryTb4b4b4:
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787databaseT7ee787.T7ee787messages Tff7b72import Te6edf3MessageDAO

Te6edf3provider Tff7b72= Te6edf3DatabaseProviderTff7b72.Td2a8ffget_instanceTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdb_pathTb4b4b4)
Te6edf3dao Tff7b72= Te6edf3MessageDAOTb4b4b4(Te6edf3providerTb4b4b4)
Te6edf3peer_hash Tff7b72= Te6edf3secretsTff7b72.Td2a8fftoken_hexTb4b4b4(T79c0ff16Tb4b4b4)
Te6edf3count Tff7b72= T79c0ff0
Tff7b72while Tff7b72not Tff7b72selfTff7b72.Td2a8ffstop_threads Tff7b72and Te6edf3count Tff7b72< T79c0ff50Tb4b4b4:
Te6edf3msg Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4: Te6edf3secretsTff7b72.Td2a8fftoken_hexTb4b4b4(T79c0ff16Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffsource_hashTa5d6ff"Tb4b4b4: Te6edf3peer_hashTb4b4b4,
Ta5d6ff"Ta5d6ffdestination_hashTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffmy_hashTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffpeer_hashTa5d6ff"Tb4b4b4: Te6edf3peer_hashTb4b4b4,
Ta5d6ff"Ta5d6ffstateTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffdeliveredTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffprogressTa5d6ff"Tb4b4b4: T79c0ff1.0Tb4b4b4,
Ta5d6ff"Ta5d6ffis_incomingTa5d6ff"Tb4b4b4: T79c0ff1Tb4b4b4,
Ta5d6ff"Ta5d6ffmethodTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffdirectTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffdelivery_attemptsTa5d6ff"Tb4b4b4: T79c0ff1Tb4b4b4,
Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4: Ta5d6fffTa5d6ff"Ta5d6ffStress Msg Tffd700{Te6edf3worker_idTffd700}Ta5d6ff-Tffd700{Te6edf3countTffd700}Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffcontentTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffATa5d6ff" Tff7b72* T79c0ff128Tb4b4b4,
Ta5d6ff"Ta5d6fffieldsTa5d6ff"Tb4b4b4: Ta5d6ff"Tffd700{}Ta5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6fftimestampTa5d6ff"Tb4b4b4: Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffrssiTa5d6ff"Tb4b4b4: Tff7b72-T79c0ff50Tb4b4b4,
Ta5d6ff"Ta5d6ffsnrTa5d6ff"Tb4b4b4: T79c0ff5.0Tb4b4b4,
Ta5d6ff"Ta5d6ffqualityTa5d6ff"Tb4b4b4: T79c0ff3Tb4b4b4,
Ta5d6ff"Ta5d6ffis_spamTa5d6ff"Tb4b4b4: T79c0ff0Tb4b4b4,
Tb4b4b4}
Tff7b72with Te6edf3providerTb4b4b4:
Te6edf3daoTff7b72.Td2a8ffupsert_lxmf_messageTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3count Tff7b72+Tff7b72= T79c0ff1
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.001Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tff7b72selfTff7b72.Td2a8fferrorsTff7b72.Td2a8ffappendTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffWriter Worker Tffd700{Te6edf3worker_idTffd700}Ta5d6ff ERROR: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)

Tff7b72def Td2a8ffdb_reader_workerTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3worker_idTb4b4b4)Tb4b4b4:
T8b949e"""Spams the message table with reads and searches."""
Tff7b72tryTb4b4b4:
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787databaseT7ee787.T7ee787announces Tff7b72import Te6edf3AnnounceDAO
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787databaseT7ee787.T7ee787messages Tff7b72import Te6edf3MessageDAO

Te6edf3provider Tff7b72= Te6edf3DatabaseProviderTff7b72.Td2a8ffget_instanceTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdb_pathTb4b4b4)
Te6edf3msg_dao Tff7b72= Te6edf3MessageDAOTb4b4b4(Te6edf3providerTb4b4b4)
Te6edf3ann_dao Tff7b72= Te6edf3AnnounceDAOTb4b4b4(Te6edf3providerTb4b4b4)

Te6edf3count Tff7b72= T79c0ff0
Tff7b72while Tff7b72not Tff7b72selfTff7b72.Td2a8ffstop_threads Tff7b72and Te6edf3count Tff7b72< T79c0ff50Tb4b4b4:
T8b949e# Perform various reads
Te6edf3msg_daoTff7b72.Td2a8ffget_conversationsTb4b4b4(Tb4b4b4)
Te6edf3ann_daoTff7b72.Td2a8ffget_filtered_announcesTb4b4b4(Te6edf3limitTff7b72=T79c0ff10Tb4b4b4)
Te6edf3count Tff7b72+Tff7b72= T79c0ff1
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.001Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tff7b72selfTff7b72.Td2a8fferrorsTff7b72.Td2a8ffappendTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffReader Worker Tffd700{Te6edf3worker_idTffd700}Ta5d6ff ERROR: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)

Tff7b72def Td2a8fftest_database_concurrencyTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Launches multiple reader and writer threads to check for lock contention."""
Te6edf3writers Tff7b72= Tb4b4b4[
Te6edf3threadingTff7b72.Td2a8ffThreadTb4b4b4(Te6edf3targetTff7b72=Tff7b72selfTff7b72.Td2a8ffdb_writer_workerTb4b4b4, Te6edf3argsTff7b72=Tb4b4b4(Te6edf3iTb4b4b4,Tb4b4b4)Tb4b4b4) Tff7b72for Te6edf3i Tff7b72in Tffa657rangeTb4b4b4(T79c0ff5Tb4b4b4)
Tb4b4b4]
Te6edf3readers Tff7b72= Tb4b4b4[
Te6edf3threadingTff7b72.Td2a8ffThreadTb4b4b4(Te6edf3targetTff7b72=Tff7b72selfTff7b72.Td2a8ffdb_reader_workerTb4b4b4, Te6edf3argsTff7b72=Tb4b4b4(Te6edf3iTb4b4b4,Tb4b4b4)Tb4b4b4) Tff7b72for Te6edf3i Tff7b72in Tffa657rangeTb4b4b4(T79c0ff5Tb4b4b4)
Tb4b4b4]

Tff7b72for Te6edf3t Tff7b72in Te6edf3writers Tff7b72+ Te6edf3readersTb4b4b4:
Te6edf3tTff7b72.Td2a8ffstartTb4b4b4(Tb4b4b4)

Tff7b72for Te6edf3t Tff7b72in Te6edf3writers Tff7b72+ Te6edf3readersTb4b4b4:
Te6edf3tTff7b72.Td2a8ffjoinTb4b4b4(Tb4b4b4)

T8b949e# Assert no errors occurred in threads
Tff7b72if Tff7b72selfTff7b72.Td2a8fferrorsTb4b4b4:
Tff7b72selfTff7b72.Td2a8fffailTb4b4b4(Ta5d6ff"Ta5d6ffErrors occurred in threads: Tffea00\nTa5d6ff" Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8fferrorsTb4b4b4)Tb4b4b4)

T8b949e# Check if we ended up with the expected number of messages
Te6edf3total Tff7b72= Tff7b72selfTff7b72.Td2a8ffdbTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchoneTb4b4b4(
Ta5d6ff"Ta5d6ffSELECT COUNT(*) as count FROM lxmf_messagesTa5d6ff"Tb4b4b4,
Tb4b4b4)Tb4b4b4[Ta5d6ff"Ta5d6ffcountTa5d6ff"Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ffassertEqualTb4b4b4(
Te6edf3totalTb4b4b4,
T79c0ff5 Tff7b72* T79c0ff50Tb4b4b4,
Ta5d6ff"Ta5d6ffTotal messages inserted doesnTa5d6ff'Ta5d6fft match expected countTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffStress test completed. Total messages inserted: Tffd700{Te6edf3totalTffd700}Ta5d6ff"Tb4b4b4)

Tff7b72def Td2a8fftest_identity_and_db_collisionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Tests potential collisions between IdentityManager and Database access."""
Te6edf3manager Tff7b72= Te6edf3IdentityManagerTb4b4b4(Tff7b72selfTff7b72.Td2a8fftest_dirTb4b4b4)

Tff7b72def Td2a8ffidentity_workerTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72for Te6edf3i Tff7b72in Tffa657rangeTb4b4b4(T79c0ff20Tb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffstop_threadsTb4b4b4:
Tff7b72break
Te6edf3managerTff7b72.Td2a8ffcreate_identityTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffStress ID Tffd700{Te6edf3iTffd700}Ta5d6ff"Tb4b4b4)
Te6edf3managerTff7b72.Td2a8fflist_identitiesTb4b4b4(Tb4b4b4)
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.01Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tff7b72selfTff7b72.Td2a8fferrorsTff7b72.Td2a8ffappendTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffIdentity Worker ERROR: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4)

Te6edf3id_thread Tff7b72= Te6edf3threadingTff7b72.Td2a8ffThreadTb4b4b4(Te6edf3targetTff7b72=Te6edf3identity_workerTb4b4b4)
Te6edf3db_thread Tff7b72= Te6edf3threadingTff7b72.Td2a8ffThreadTb4b4b4(
Te6edf3targetTff7b72=Tff7b72selfTff7b72.Td2a8ffdb_writer_workerTb4b4b4,
Te6edf3argsTff7b72=Tb4b4b4(Ta5d6ff"Ta5d6ffid_collisionTa5d6ff"Tb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)

Te6edf3id_threadTff7b72.Td2a8ffstartTb4b4b4(Tb4b4b4)
Te6edf3db_threadTff7b72.Td2a8ffstartTb4b4b4(Tb4b4b4)

Te6edf3id_threadTff7b72.Td2a8ffjoinTb4b4b4(Tb4b4b4)
Te6edf3db_threadTff7b72.Td2a8ffjoinTb4b4b4(Tb4b4b4)

T8b949e# Assert no errors occurred
Tff7b72if Tff7b72selfTff7b72.Td2a8fferrorsTb4b4b4:
Tff7b72selfTff7b72.Td2a8fffailTb4b4b4(Ta5d6ff"Ta5d6ffErrors occurred in threads: Tffea00\nTa5d6ff" Tff7b72+ Ta5d6ff"Tffea00\nTa5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8fferrorsTb4b4b4)Tb4b4b4)

Te6edf3identities Tff7b72= Te6edf3managerTff7b72.Td2a8fflist_identitiesTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertEqualTb4b4b4(Tffa657lenTb4b4b4(Te6edf3identitiesTb4b4b4)Tb4b4b4, T79c0ff20Tb4b4b4, Ta5d6ff"Ta5d6ffShould have created 20 identitiesTa5d6ff"Tb4b4b4)

Te6edf3total_messages Tff7b72= Tff7b72selfTff7b72.Td2a8ffdbTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchoneTb4b4b4(
Ta5d6ff"Ta5d6ffSELECT COUNT(*) as count FROM lxmf_messagesTa5d6ff"Tb4b4b4,
Tb4b4b4)Tb4b4b4[Ta5d6ff"Ta5d6ffcountTa5d6ff"Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ffassertEqualTb4b4b4(
Te6edf3total_messagesTb4b4b4,
T79c0ff50Tb4b4b4,
Ta5d6ff"Ta5d6ffShould have inserted 50 messages during collision testTa5d6ff"Tb4b4b4,
Tb4b4b4)


Tff7b72if Tff7b72__name__ Tff7b72== Ta5d6ff"Ta5d6ff__main__Ta5d6ff"Tb4b4b4:
Te6edf3unittestTff7b72.Td2a8ffmainTb4b4b4(Tb4b4b4)


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────